import sqlite3
import pandas as pd
import numpy as np
from collections import Counter
import random
from datetime import datetime
import matplotlib.pyplot as plt

class SSQPredictor:
    def __init__(self):
        print("[DEBUG] 正在连接数据库 lottery.db...")
        try:
            self.conn = sqlite3.connect('lottery.db')
            print("[DEBUG] 数据库连接成功")
        except Exception as e:
            print(f"[ERROR] 数据库连接失败: {e}")
            raise
            
        self.recent_draws = 100  # 分析最近100期数据
        self.red_balls_range = range(1, 34)  # 红球范围1-33
        self.blue_balls_range = range(1, 17)  # 蓝球范围1-16
        print(f"[DEBUG] 初始化完成，分析最近 {self.recent_draws} 期数据")
        
    def get_historical_data(self):
        """获取历史开奖数据"""
        print(f"[DEBUG] 正在查询最近 {self.recent_draws} 期开奖数据...")
        query = """
            SELECT draw_num, draw_date, 
                   red_ball_1, red_ball_2, red_ball_3, red_ball_4, red_ball_5, red_ball_6, 
                   blue_ball
            FROM lottery_draws
            ORDER BY draw_num DESC
            LIMIT ?
        """
        
        try:
            df = pd.read_sql_query(query, self.conn, params=(self.recent_draws,))
            print(f"[DEBUG] 成功获取 {len(df)} 条开奖记录")
            if len(df) == 0:
                print("[WARNING] 查询结果为空，请检查数据库是否有数据")
            return df
        except Exception as e:
            print(f"[ERROR] 数据查询失败: {e}")
            raise
    
    def analyze_frequency(self, df):
        """分析号码出现频率"""
        # 红球频率分析
        red_balls = []
        for i in range(1, 7):
            red_balls.extend(df[f'red_ball_{i}'].tolist())
        
        red_freq = Counter(red_balls)
        for num in self.red_balls_range:
            if num not in red_freq:
                red_freq[num] = 0
        
        # 蓝球频率分析
        blue_freq = Counter(df['blue_ball'])
        for num in self.blue_balls_range:
            if num not in blue_freq:
                blue_freq[num] = 0
        
        return red_freq, blue_freq
    
    def analyze_hot_cold(self, red_freq, blue_freq):
        """分析冷热号"""
        # 按频率排序
        sorted_red = sorted(red_freq.items(), key=lambda x: x[1], reverse=True)
        sorted_blue = sorted(blue_freq.items(), key=lambda x: x[1], reverse=True)
        
        # 热号(出现频率前1/3)
        hot_red = [num for num, _ in sorted_red[:11]]
        hot_blue = [num for num, _ in sorted_blue[:5]]
        
        # 温号(出现频率中间1/3)
        warm_red = [num for num, _ in sorted_red[11:22]]
        warm_blue = [num for num, _ in sorted_blue[5:10]]
        
        # 冷号(出现频率后1/3)
        cold_red = [num for num, _ in sorted_red[22:]]
        cold_blue = [num for num, _ in sorted_blue[10:]]
        
        return {
            'hot_red': hot_red,
            'warm_red': warm_red,
            'cold_red': cold_red,
            'hot_blue': hot_blue,
            'warm_blue': warm_blue,
            'cold_blue': cold_blue
        }
    
    def analyze_missing_values(self, df):
        """分析遗漏值"""
        # 获取最近一期的期号
        latest_draw_num = df['draw_num'].iloc[0]
        
        # 初始化遗漏值字典
        red_missing = {num: 0 for num in self.red_balls_range}
        blue_missing = {num: 0 for num in self.blue_balls_range}
        
        # 计算每个号码的遗漏值
        for _, row in df.iterrows():
            red_numbers = [row[f'red_ball_{i}'] for i in range(1, 7)]
            blue_number = row['blue_ball']
            
            # 更新已出现号码的遗漏值为0
            for num in red_numbers:
                if red_missing[num] != -1:  # -1表示已经计算过遗漏值
                    red_missing[num] = -1
            
            if blue_missing[blue_number] != -1:
                blue_missing[blue_number] = -1
            
            # 增加未出现号码的遗漏值
            for num in self.red_balls_range:
                if red_missing[num] != -1:
                    red_missing[num] += 1
            
            for num in self.blue_balls_range:
                if blue_missing[num] != -1:
                    blue_missing[num] += 1
        
        # 移除-1标记
        for num in self.red_balls_range:
            if red_missing[num] == -1:
                red_missing[num] = 0
        
        for num in self.blue_balls_range:
            if blue_missing[num] == -1:
                blue_missing[num] = 0
        
        return red_missing, blue_missing
    
    def analyze_sum_and_distribution(self, df):
        """分析和值与分布"""
        # 计算红球和值
        df['red_sum'] = df.apply(lambda row: sum(row[f'red_ball_{i}'] for i in range(1, 7)), axis=1)
        
        # 计算红球奇偶比
        df['red_odd_count'] = df.apply(lambda row: sum(1 for i in range(1, 7) if row[f'red_ball_{i}'] % 2 == 1), axis=1)
        df['red_even_count'] = 6 - df['red_odd_count']
        
        # 计算红球大小比(1-16为小号，17-33为大号)
        df['red_small_count'] = df.apply(lambda row: sum(1 for i in range(1, 7) if row[f'red_ball_{i}'] <= 16), axis=1)
        df['red_big_count'] = 6 - df['red_small_count']
        
        # 计算红球区间分布(1-11,12-22,23-33)
        df['red_zone1_count'] = df.apply(lambda row: sum(1 for i in range(1, 7) if 1 <= row[f'red_ball_{i}'] <= 11), axis=1)
        df['red_zone2_count'] = df.apply(lambda row: sum(1 for i in range(1, 7) if 12 <= row[f'red_ball_{i}'] <= 22), axis=1)
        df['red_zone3_count'] = df.apply(lambda row: sum(1 for i in range(1, 7) if 23 <= row[f'red_ball_{i}'] <= 33), axis=1)
        
        # 统计分析结果
        sum_stats = {
            'red_sum_mean': df['red_sum'].mean(),
            'red_sum_median': df['red_sum'].median(),
            'red_sum_min': df['red_sum'].min(),
            'red_sum_max': df['red_sum'].max(),
            'odd_even_ratio': df.groupby(['red_odd_count', 'red_even_count']).size().sort_values(ascending=False).head(3).to_dict(),
            'big_small_ratio': df.groupby(['red_small_count', 'red_big_count']).size().sort_values(ascending=False).head(3).to_dict(),
            'zone_distribution': df.groupby(['red_zone1_count', 'red_zone2_count', 'red_zone3_count']).size().sort_values(ascending=False).head(3).to_dict()
        }
        
        return sum_stats
    
    def analyze_consecutive_numbers(self, df):
        """分析连号情况"""
        consecutive_counts = []
        
        for _, row in df.iterrows():
            red_numbers = sorted([row[f'red_ball_{i}'] for i in range(1, 7)])
            count = 0
            for i in range(len(red_numbers) - 1):
                if red_numbers[i+1] - red_numbers[i] == 1:
                    count += 1
            consecutive_counts.append(count)
        
        consecutive_stats = Counter(consecutive_counts)
        return consecutive_stats
    
    def generate_predictions(self, count=10):
        """deepseekv3生成预测号码"""
        print("[DEBUG] 开始生成预测号码...")
        print(f"[DEBUG] 将生成 {count} 组预测号码")
        
        df = self.get_historical_data()
        print("[DEBUG] 正在分析号码频率...")
        red_freq, blue_freq = self.analyze_frequency(df)
        
        print("[DEBUG] 正在分析冷热号...")
        hot_cold_analysis = self.analyze_hot_cold(red_freq, blue_freq)
        
        print("[DEBUG] 正在分析遗漏值...")
        red_missing, blue_missing = self.analyze_missing_values(df)
        
        print("[DEBUG] 正在分析和值与分布...")
        sum_stats = self.analyze_sum_and_distribution(df)
        
        print("[DEBUG] 正在分析连号情况...")
        consecutive_stats = self.analyze_consecutive_numbers(df)
        
        # 打印分析结果
        print("=== deepseek双色球号码预测分析 ===\n")
        print(f"分析基于最近{self.recent_draws}期开奖数据")
        print(f"当前日期: {datetime.now().strftime('%Y-%m-%d')}\n")
        
        print("红球热号(高频号码):", hot_cold_analysis['hot_red'])
        print("红球温号(中频号码):", hot_cold_analysis['warm_red'])
        print("红球冷号(低频号码):", hot_cold_analysis['cold_red'])
        print("\n蓝球热号:", hot_cold_analysis['hot_blue'])
        print("蓝球温号:", hot_cold_analysis['warm_blue'])
        print("蓝球冷号:", hot_cold_analysis['cold_blue'])
        
        print("\n红球遗漏值前10名:")
        sorted_red_missing = sorted(red_missing.items(), key=lambda x: x[1], reverse=True)[:10]
        for num, missing in sorted_red_missing:
            print(f"号码 {num}: 遗漏{missing}期")
        
        print("\n蓝球遗漏值前5名:")
        sorted_blue_missing = sorted(blue_missing.items(), key=lambda x: x[1], reverse=True)[:5]
        for num, missing in sorted_blue_missing:
            print(f"号码 {num}: 遗漏{missing}期")
        
        print(f"\n红球和值统计: 平均值 {sum_stats['red_sum_mean']:.2f}, 中位数 {sum_stats['red_sum_median']}, 范围 {sum_stats['red_sum_min']}-{sum_stats['red_sum_max']}")
        
        print("\n最常见的奇偶比例:")
        for (odd, even), count in list(sum_stats['odd_even_ratio'].items())[:3]:
            print(f"奇数{odd}个:偶数{even}个 - 出现{count}次")
        
        print("\n最常见的大小比例:")
        for (small, big), count in list(sum_stats['big_small_ratio'].items())[:3]:
            print(f"小号{small}个:大号{big}个 - 出现{count}次")
        
        print("\n最常见的区间分布:")
        for (zone1, zone2, zone3), count in list(sum_stats['zone_distribution'].items())[:3]:
            print(f"前区{zone1}个:中区{zone2}个:后区{zone3}个 - 出现{count}次")
        
        print("\n连号统计:")
        for consec_count, freq in sorted(consecutive_stats.items()):
            print(f"{consec_count}组连号: 出现{freq}次")
        
        # 获取最常见的奇偶比例和大小比例
        common_odd_even = list(sum_stats['odd_even_ratio'].keys())[0]
        common_big_small = list(sum_stats['big_small_ratio'].keys())[0]
        common_zone_dist = list(sum_stats['zone_distribution'].keys())[0]
        
        # 生成预测号码
        predictions = []
        for _ in range(count):
            valid_combination = False
            attempts = 0
            
            while not valid_combination and attempts < 10:
                attempts += 1
                # 根据分析结果生成红球
                red_candidates = set()
                
                # 加入一些热号
                red_candidates.update(random.sample(hot_cold_analysis['hot_red'], k=min(2, len(hot_cold_analysis['hot_red']))))
                
                # 加入一些温号
                red_candidates.update(random.sample(hot_cold_analysis['warm_red'], k=min(2, len(hot_cold_analysis['warm_red']))))
                
                # 加入一些遗漏值较高的号码
                high_missing_reds = [num for num, _ in sorted_red_missing[:5]]
                red_candidates.update(random.sample(high_missing_reds, k=min(1, len(high_missing_reds))))
                
                # 如果不足6个，从剩余号码中随机选择
                remaining_count = 6 - len(red_candidates)
                if remaining_count > 0:
                    remaining_numbers = list(set(self.red_balls_range) - red_candidates)
                    red_candidates.update(random.sample(remaining_numbers, k=remaining_count))
                
                # 确保只有6个红球
                if len(red_candidates) > 6:
                    red_candidates = set(random.sample(list(red_candidates), k=6))
                
                # 转换为列表并排序
                red_candidates = sorted(list(red_candidates))
                
                # 验证组合是否符合常见模式
                odd_count = sum(1 for num in red_candidates if num % 2 == 1)
                even_count = 6 - odd_count
                
                small_count = sum(1 for num in red_candidates if num <= 16)
                big_count = 6 - small_count
                
                zone1_count = sum(1 for num in red_candidates if 1 <= num <= 11)
                zone2_count = sum(1 for num in red_candidates if 12 <= num <= 22)
                zone3_count = sum(1 for num in red_candidates if 23 <= num <= 33)
                
                # 计算连号数
                consecutive_count = 0
                for i in range(len(red_candidates) - 1):
                    if red_candidates[i+1] - red_candidates[i] == 1:
                        consecutive_count += 1
                
                # 计算和值
                red_sum = sum(red_candidates)
                
                # 检查是否符合常见模式
                if (abs(odd_count - common_odd_even[0]) <= 1 and 
                    abs(small_count - common_big_small[0]) <= 1 and 
                    abs(zone1_count - common_zone_dist[0]) <= 1 and 
                    abs(zone2_count - common_zone_dist[1]) <= 1 and 
                    abs(zone3_count - common_zone_dist[2]) <= 1 and 
                    consecutive_count in [0, 1, 2] and 
                    sum_stats['red_sum_min'] <= red_sum <= sum_stats['red_sum_max']):
                    valid_combination = True
            
            # 生成蓝球
            blue_candidates = []
            
            # 有70%的概率选择热门蓝球
            if random.random() < 0.7:
                blue_candidates.extend(hot_cold_analysis['hot_blue'])
            else:
                # 有30%的概率选择遗漏值高的蓝球
                high_missing_blues = [num for num, _ in sorted_blue_missing[:3]]
                blue_candidates.extend(high_missing_blues)
            
            # 如果没有候选蓝球，从所有蓝球中随机选择
            if not blue_candidates:
                blue_candidates = list(self.blue_balls_range)
            
            blue_ball = random.choice(blue_candidates)
            
            # 添加到预测结果
            predictions.append((red_candidates, blue_ball))
        
        print("\n=== 推荐号码组合 ===\n")
        for i, (red_balls, blue_ball) in enumerate(predictions, 1):
            print(f"第{i}组: {', '.join(str(num) for num in red_balls)} + {blue_ball}")
        
        # 生成胆拖推荐
        print("\n=== 胆拖推荐 ===\n")
        dan_tuo_recommendations = []
        
        # 选择2-3个热号作为胆码
        dan_numbers = random.sample(hot_cold_analysis['hot_red'], k=random.randint(2, 3))
        
        # 从剩余号码中选择拖码
        tuo_numbers = list(set(self.red_balls_range) - set(dan_numbers))
        
        # 生成5组胆拖组合
        for _ in range(5):
            # 从拖码中选择6 - len(dan_numbers)个号码
            selected_tuo = random.sample(tuo_numbers, k=6 - len(dan_numbers))
            combined = sorted(dan_numbers + selected_tuo)
            
            # 验证组合是否符合常见模式
            odd_count = sum(1 for num in combined if num % 2 == 1)
            small_count = sum(1 for num in combined if num <= 16)
            zone1_count = sum(1 for num in combined if 1 <= num <= 11)
            zone2_count = sum(1 for num in combined if 12 <= num <= 22)
            zone3_count = sum(1 for num in combined if 23 <= num <= 33)
            
            if (abs(odd_count - common_odd_even[0]) <= 1 and 
                abs(small_count - common_big_small[0]) <= 1 and 
                abs(zone1_count - common_zone_dist[0]) <= 1 and 
                abs(zone2_count - common_zone_dist[1]) <= 1 and 
                abs(zone3_count - common_zone_dist[2]) <= 1):
                dan_tuo_recommendations.append((dan_numbers, selected_tuo))
        
        # 打印胆拖推荐
        print(f"胆码: {', '.join(str(num) for num in dan_numbers)}")
        for i, (dan, tuo) in enumerate(dan_tuo_recommendations, 1):
            print(f"第{i}组拖码: {', '.join(str(num) for num in tuo)}")
        
        return predictions

if __name__ == "__main__":
    predictor = SSQPredictor()
    predictor.generate_predictions(5)